
////////////////////////////////////////////////////////////////////////////
//	File Name: TSparseVector.h		Last modification at : 2/13/2003 2:01:29 AM
//	Copyright 1999-2003 Microsoft Corporation. All Rights Reserved.
//
//	Author:      Rong Xiao
//	Email :      t-rxiao@microsoft.com
//
//	Description : 
//
//	Revision History: 
//
////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __TSPARSEVECTOR_H__
#define __TSPARSEVECTOR_H__

#include "tvector.h"

namespace FAST
{

template <typename T> class TSparseVector;
template <typename T> class TSparseMatrix;

typedef TSparseVector<float>	TFloatSparseVector;
typedef TSparseVector<double>	TDoubleSparseVector;
typedef TSparseVector<int>		TIntSparseVector;
typedef TSparseVector<short>	TShortSparseVector;
typedef TSparseVector<char>		TCharSparseVector;
typedef TSparseVector<unsigned int>	TUIntSparseVector;
typedef TSparseVector<unsigned short>	TUShortSparseVector;
typedef TSparseVector<unsigned char>	TByteSparseVector;


// @typename 
//   This is the template of the Vector typename. It defined all kind of Vector of Vector,
//		I/O and the conversion to other types.
//
// @tcarg typename | T | This is the element type of Vector
//
template <typename T>
class TSparseVector  
{
protected:
//***************************************************
//	Section 1:	Protected Data Members
//***************************************************

	// @cmember This is the pointer to the data buffer.
	std::vector< T >   m_ValueList;
	std::vector< unsigned int > m_IndexList; 

	// @cmember This is the dim of a Vector.
	unsigned int m_Dim;

	//Search the unit index in given index
	// ret > 0, the index in m_data
	// ret < 0, the index is between m_data[ret+nLen] m_data[ret+nLen+1]
	int SearchIndex( unsigned nDim) const;

public:

//********************************************************
//		Section 3: Memory Allocation and DeAlloc
//********************************************************/

	// @cmember Release the memory if needed.
	inline void Destroy() { m_ValueList.clear(); m_IndexList.clear(); m_Dim=0; }	

//********************************************************
//		Section 4: Constructors and Destructors
//********************************************************/
	// @cmember Constructor
	inline TSparseVector() :	m_Dim(0) {}

	// @cmember Constructor, 
	//Defined for efficiency, the ptr will be destroyed by the destructor
	inline TSparseVector(TVector<T>& ref)  { *this=ref; }

	// @cmember Constructor
	inline TSparseVector(const unsigned int nDim) : m_Dim(nDim) {}

	// @cmember Constructor
	inline TSparseVector(const TSparseVector<T>& ref) : m_Dim(ref.m_Dim), m_ValueList(ref.m_ValueList), m_IndexList(ref.m_IndexList) {};

	// @cmember Destructor
	inline ~TSparseVector()	{		Destroy();	}	
	
//*************************************************
//		Section 5: Get and set Vector properties
//*************************************************
	// @cmember Get the size of vector
	inline int GetDim() const 	{	return m_Dim;		}
    
	inline void NewSize(int nDim) { Destroy(); m_Dim=nDim; }

	inline void ResizeSparseBuffer(unsigned int nSize) {
		assert ( nSize>=0 );
		m_IndexList.resize(nSize);
		m_ValueList.resize(nSize);
	}

	inline void ReserveSparseBuffer(unsigned int nSize) {
		assert ( nSize>=0 );
		m_IndexList.reserve(nSize);
		m_ValueList.reserve(nSize);
	}

	// Get the nonzero list
	inline int GetLen() const  { return m_IndexList.size(); }

	inline int GetSparseIndex(int nIndex) const { assert ( nIndex>=0 && nIndex<GetLen()); return m_IndexList[nIndex]; }
	
	inline T GetSparseValue(int nIndex) const { assert ( nIndex>=0 && nIndex<GetLen()); return m_ValueList[nIndex]; }
	
//***************************************************
//	Section 6: Data Operating
//***************************************************
	/**********************************************************
		Section 6.1: Set/Get Values
	**********************************************************/

	// @cmember Add an element, make sure the input index > last index
	inline void push_back(unsigned int index, T Value);
	
	// @cmember set an element's value,base 0
	inline void SetAt(int nDim, T NewValue) ;

	// @cmember get an element's value,base 0
	inline T GetAt(int nDim) const;
	
	inline char* GetSparseIndexPtr() { 
		if ( GetLen() )			return (char*)&m_IndexList[0]; 
		else 		return 0;
	}

	inline char* GetSparseValuePtr() { 
		if ( GetLen() )		return (char*)&m_ValueList[0]; 
		else 	return 0;
	}

	// @cmember write down the vector
    inline int Write(const char* szFname, bool bBinary=false) const;
    inline int Write(std::ostream& Fout, bool bBinary=false) const;

    // @cmember read the vector
    inline int Read(const char* szFname, bool bBinary=false);
    inline int Read(std::istream& Fin, bool bBinary=false);

	/*********************************************************
		Section 6.3: Type Cast operation
	*********************************************************/
	// @cmember Type convertor between difference types
	inline operator TCharSparseVector() const;
	inline operator TShortSparseVector() const;
	inline operator TIntSparseVector() const;
	inline operator TByteSparseVector() const;
	inline operator TUShortSparseVector() const;
	inline operator TUIntSparseVector() const;
	inline operator TFloatSparseVector() const;
	inline operator TDoubleSparseVector() const;
	inline operator TSparseMatrix<T>() const;	

	inline operator TMatrix<T>() const;
	inline operator TVector<T>() const;

//***************************************************
//	Section 7:  OverRide Operation 
//***************************************************
	// @cmember Operator [], used to access the element of Vector
	//		This is const version, It is necessary.
	inline  T operator[](int nDim) const ;
	

	// @cmember Vector multiple
	inline T operator*(const TSparseVector<T>& ref) const;

	// @cmember Vector multiple
	inline T operator*(const TVector<T>& ref) const;
	
	// @cmember Vector multiple
	inline TVector<T> operator*(const TSparseMatrix<T>& ref) const;

	// @cmember Vector multiple
	inline TVector<T> operator*(const TMatrix<T>& ref) const;

	
	// @cmember multiple a numeric
	inline TSparseVector<T> operator*(const T scale) const;

	// @cmember all the elements divide a numeric
	inline TSparseVector<T> operator/(const T scale) const;
	
	// @cmember multiple a numeric to all the element
	void operator*=(const T scale);

	// @cmember each elements divide a numeric
	void operator/=(const T scale);

//************************************************
//	Section 8:	Vector Computation 
//************************************************
	//return the max value of vect
	inline T Max(void) const;
	
	//return the min value of vect
	inline T Min(void) const;
	
	//return the max value pos of vect
	inline int MaxPos(void) const;
	
	//return the min value pos of vect
	inline int MinPos(void) const;
	
	// @cmember return sum of all elements
	inline double Sum(void) const;
	inline T TSum(void) const;

	// @cmember return mean of Vector
	inline double Mean(void) const;
	inline T TMean(void) const;

	// Compute ABS vector
	inline TSparseVector<T> abs(void) const;
	
   	// @cmember Get the Variance of this vector (in double)
	inline double GetVariance(void) const;

    // @cmember return 2-norm the vector 
    inline double GetNorm2(void) const;
	inline T TGetNorm2(void) const;

    // @cmember return norm of the vector 
    inline double GetNorm(void) const;



//************************************************
//	Section 8:	Friend Functions
//************************************************
	friend  inline std::istream & operator >> (std::istream& is, TSparseVector<T>& vect);
	friend  inline std::ostream & operator << (std::ostream& os, const TSparseVector<T>& vect);

};  //End of typename TSparseVector

template <typename T> inline std::istream & operator >> (std::istream& is, TSparseVector<T>& vect);
template <typename T> inline std::ostream & operator << (std::ostream& os, const TSparseVector<T>& vect);

	
#include "TSparseVector.inl"
	
}	//End of namespace FAST

#endif				 // End of __TSPARSEVECTOR_H__
